package step6;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
/**
 * 채팅 서버 
 * 리스트에 worker 객체를 저장한다. 
 * 개별 worker에서 broadcast() 를 호출하면 
 * 전체 client에게 메세지를 출력한다. 
 * @author kosta-00-kangsa-001
 *
 */
public class ChattingServer {
	//전체 worker 가 저장되어 있는 리스트
	private ArrayList list=new ArrayList();
	private ServerSocket serverSocket;
	/**
	 * ServerSocket 생성 
	 * while
	 * accept() 수행하여 Socket 반환 
	 * ChattingWorker 생성(socket)
	 * list에 추가 
	 * Thread 생성
	 * start() 
	 * @throws IOException 
	 */
	public void go() throws IOException{
		serverSocket=new ServerSocket(5432);
		while(true){
			Socket socket=serverSocket.accept();
			ChattingWorker worker=new ChattingWorker(socket);
			Thread thread=new Thread(worker);
			list.add(worker);
			thread.start();
		}
	}
	/**
	 * for loop 를 수행하면서 전체 클라이언트에게 
	 * 메세지를 출력한다. 
	 * 개별 클라이언트에게 메세지를 출력 
		worker 의 socket output -> pw.println(message)
		sendMessage(message)
	 * @param message
	 */
	public void broadcast(String message){
		for(int i=0;i<list.size();i++){
			ChattingWorker worker=(ChattingWorker)list.get(i);
			worker.sendMessage(message);
		}
	}
	class ChattingWorker implements Runnable{
		private Socket socket;
		private BufferedReader br;
		private PrintWriter pw;
		private String user;
		public ChattingWorker(Socket socket) {
			this.socket=socket;
			user="["+socket.getInetAddress().toString()+"]";
			System.out.println(user+"입장하셨습니다");
			broadcast(user+"입장하셨습니다");
		}
		//방가를 읽는다-> broadcast(방가)
		public void chatting() throws IOException{
			br=new BufferedReader(
					new InputStreamReader(socket.getInputStream()));
			pw=new PrintWriter(socket.getOutputStream(),true);
			while(true){
				String mess=br.readLine();
				if(mess==null){
					System.out.println(user+"님이 나가셨습니다");
					broadcast(user+"님이 나가셨습니다");
					list.remove(this);//리스트에서 삭제시킨다. 					
					break;
				}
				broadcast(user+"님의 메세지:"+mess);
			}
		}
		/**
		 * 자신과 연결된 개별 클라이언트에게 메세지를 출력
		 * @param message
		 */
		public void sendMessage(String message){
			pw.println(message);
		}
		@Override
		public void run() {
			try {
				System.out.println("채팅 서버 실행중");
				chatting();
			} catch (IOException e) {				
				e.printStackTrace();
			} finally{
				try {
					closeAll();
				} catch (IOException e) {				
					e.printStackTrace();
				}
			}
		}	
		public void closeAll() throws IOException{
			if(pw!=null)
				pw.close();
			if(br!=null)
				br.close();
			if(socket!=null)
				socket.close();
		}
		
	}	
	public static void main(String[] args) {		
		ChattingServer server=new ChattingServer();
		try {
			System.out.println("============Chat Server Start==============");
			server.go();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}	
}










